package com.way.fileexplorer.util;

// Porting from xingxing
// TODO: MERGE IT INTO FILEUTIL

import java.io.File;
import java.text.Collator;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;

import android.provider.MediaStore.MediaColumns;
import android.util.Log;

public class FileSort {
    public static final String TAG = "FileSort";
    public static final String FILE_SORT_KEY = "sort_key";
    public static final int START_SORT = 0;
    public static final int SORT_BY_NAME = 1;
    public static final int SORT_BY_TYPE = 2;
    public static final int SORT_BY_TIME_DESC = 3;
    public static final int SORT_BY_TIME_ASC = 4;
    public static final int SORT_BY_SIZE_DESC = 5;
    public static final int SORT_BY_SIZE_ASC = 6;
    public static final int SORT_BY_NAME_DESC = 7;
    public static final int SORT_BY_TYPE_DESC = 8;

    private int mSortType;

    private Comparator<File> comparator;

    private static FileSort mFileListSort = null;

    public FileSort(int sortType) {
        setSortType(sortType);
    }

    public void sort(List<File> fileList) {
        if (null == fileList) {
            return;
        }
        Collections.sort(fileList, comparator);
    }

    private FileSort() {
        setSortType(SORT_BY_NAME);
        System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
    }

    public static FileSort getFileListSort() {
        if (mFileListSort == null) {
            mFileListSort = new FileSort();
        }
        return mFileListSort;
    }

    public static void fileListSort(List<File> fileList) {
        Collections.sort(fileList, getFileListSort().comparator);
    }

    public static String getOrderStr(int order) {
        String ret = null;
        switch (order) {
        case SORT_BY_NAME:
            ret = MediaColumns.TITLE + " collate nocase, " + MediaColumns.DATA + " collate nocase";
            break;
        case SORT_BY_NAME_DESC:
            ret = MediaColumns.TITLE + " collate nocase desc, " + MediaColumns.DATA+ " collate nocase desc";
            break;
        case SORT_BY_TYPE:
            ret = MediaColumns.MIME_TYPE + ", " + MediaColumns.TITLE + ", " + MediaColumns.DATA;
            break;
        case SORT_BY_TYPE_DESC:
            ret = MediaColumns.MIME_TYPE + " desc, " + MediaColumns.TITLE + " desc, " +  MediaColumns.DATA+ " desc";
            break;
        case SORT_BY_TIME_DESC:
            ret = MediaColumns.DATE_MODIFIED+ " desc, " + MediaColumns.TITLE + " desc, " +  MediaColumns.DATA+ " desc";
            break;
        case SORT_BY_TIME_ASC:
            ret = MediaColumns.DATE_MODIFIED + ", " + MediaColumns.TITLE + ", " + MediaColumns.DATA;
            break;
        case SORT_BY_SIZE_DESC:
            ret = MediaColumns.SIZE + " desc, " + MediaColumns.TITLE + " desc, " +  MediaColumns.DATA+ " desc";
            break;
        case SORT_BY_SIZE_ASC:
            ret = MediaColumns.SIZE + ", " + MediaColumns.TITLE + ", " + MediaColumns.DATA;
            break;
        }
        return ret;
    }

    public void setSortType(int sortType) {
        if (sortType > SORT_BY_TYPE_DESC || sortType < SORT_BY_NAME) {
            sortType = SORT_BY_NAME;
            Log.e("FileSort", "the argument: sortType = " + sortType + " out of border");
        }
        mSortType = sortType;
        switch (mSortType) {
        case SORT_BY_NAME:
            comparator = new Comparator<File>() {

                @Override
                public int compare(File lhs, File rhs) {
                    int ret = compareDirFile(lhs, rhs, false);
                    if (ret == 0) {
                        Collator myCollator = Collator.getInstance(java.util.Locale.CHINA);
                        ret = myCollator.compare(lhs.getName().toLowerCase(), rhs.getName().toLowerCase());
                    }
                    return ret;
                }

            };
            break;
        case SORT_BY_NAME_DESC:
            comparator = new Comparator<File>() {

                @Override
                public int compare(File lhs, File rhs) {
                    int ret = compareDirFile(lhs, rhs, true);
                    if (ret == 0) {
                        Collator myCollator = Collator.getInstance(java.util.Locale.CHINA);
                        ret = myCollator.compare(lhs.getName().toLowerCase(), rhs.getName().toLowerCase());
                    }
                    return -ret;
                }

            };
            break;
        case SORT_BY_TYPE:
            comparator = new Comparator<File>() {

                @Override
                public int compare(File lhs, File rhs) {
                    int ret = compareDirFile(lhs, rhs, false);
                    if (ret == 0) {
                        String lhsName = lhs.getName();
                        String rhsName = rhs.getName();
                        String lhsType = getFileType(lhsName);
                        String rhsType = getFileType(rhsName);
                        ret = lhsType.compareTo(rhsType);
                        if (ret == 0) {
                            ret = lhsName.compareTo(rhsName);
                        }if (ret == 0) {
                            ret = lhs.getPath().compareTo(rhs.getPath());
                        }
                    }
                    Log.i(TAG,"compare " + lhs.getPath() + " AND " + rhs.getPath() + ", retutn " + ret);
                    return ret;
                }

            };
            break;
        case SORT_BY_TYPE_DESC:
            comparator = new Comparator<File>() {

                @Override
                public int compare(File lhs, File rhs) {
                    int ret = compareDirFile(lhs, rhs, true);
                    if (ret == 0) {
                        String lhsName = lhs.getName();
                        String rhsName = rhs.getName();
                        String lhsType = getFileType(lhsName);
                        String rhsType = getFileType(rhsName);
                        ret = lhsType.compareTo(rhsType);
                        if (ret == 0) {
                            ret = lhsName.compareTo(rhsName);
                        }
                    }
                    return -ret;
                }

            };
            break;
        case SORT_BY_TIME_ASC:
            comparator = new Comparator<File>() {

                @Override
                public int compare(File lhs, File rhs) {
                    return compareTime(lhs, rhs, false);
                }

            };
            break;
        case SORT_BY_TIME_DESC:
            comparator = new Comparator<File>() {

                @Override
                public int compare(File lhs, File rhs) {
                    return -compareTime(lhs, rhs, true);
                }

            };
            break;
        case SORT_BY_SIZE_ASC:
            comparator = new Comparator<File>() {
                @Override
                public int compare(File lhs, File rhs) {
                    return compareSize(lhs, rhs, false);
                }
            };
            break;
        case SORT_BY_SIZE_DESC:
            comparator = new Comparator<File>() {

                @Override
                public int compare(File lhs, File rhs) {
                    return -compareSize(lhs, rhs, true);
                }

            };
            break;
        }
    }

    public int getSortType() {
        return mSortType;
    }

    private String getFileType(String fileName) {
        String ret = "";
        int index = fileName.lastIndexOf(".");
        if (index != -1) {
            ret = fileName.substring(index + 1).toLowerCase(Locale.US);
        }
        return ret;
    }

    private int compareDirFile(File lhs, File rhs, boolean isDes) {
        if (lhs.isDirectory() && rhs.isFile()) {
            return isDes ? 1 :-1;
        } else if (lhs.isFile() && rhs.isDirectory()) {
            return isDes ? -1 :1;
        } else {
            return 0;
        }
    }

    private int compareTime(File lhs, File rhs, boolean isDes) {
        int ret = compareDirFile(lhs, rhs, isDes);
        if (ret == 0) {
            ret = (int) (lhs.lastModified() - rhs.lastModified());
            if(lhs.lastModified() > rhs.lastModified()){
                ret = 1;
            }else if(lhs.lastModified() < rhs.lastModified()){
                ret = -1;
            }else{
                ret = 0;
            }
            if (ret == 0) {
                Log.i(TAG, "time is equal, compare the name");
                Collator myCollator = Collator
                        .getInstance(java.util.Locale.CHINA);
                ret = myCollator.compare(lhs.getName().toLowerCase(), rhs
                        .getName().toLowerCase());
                if (ret == 0) {
                    Log.i(TAG, "if time and name is equal, copmare the file");
                    ret = rhs.compareTo(rhs);
                }
            }
        }
        return ret;
    }

    private int compareSize(File lhs, File rhs, boolean isDes) {
        int ret = compareDirFile(lhs, rhs, isDes);
        if (ret == 0) {
            ret = (int) (lhs.length() - rhs.length());
            if (ret == 0) {
                Log.i(TAG, "time is equal, compare the name");
                Collator myCollator = Collator
                        .getInstance(java.util.Locale.CHINA);
                ret = myCollator.compare(lhs.getName().toLowerCase(), rhs
                        .getName().toLowerCase());
                if (ret == 0) {
                    Log.i(TAG, "time and name is equal, compare the file");
                    ret = lhs.compareTo(rhs);
                }
            }
        }
        return ret;
    }
    
    public static int getSelectItemByType(int type){
        switch(type){
        case SORT_BY_TYPE:
        case SORT_BY_TYPE_DESC:
            return 1;
        case SORT_BY_NAME:
        case SORT_BY_NAME_DESC:
            return 0;
        case SORT_BY_SIZE_ASC:
        case SORT_BY_SIZE_DESC:
            return 3;
        case SORT_BY_TIME_DESC:
        case SORT_BY_TIME_ASC:
            return 2;
        default:
            return 0;
        }
    }

}
